﻿using System;
using System.Collections.Generic;
using System.Text;
using Geometry;
using System.Collections;
using PotentialFieldDriver;

namespace PotentialFieldDriver
{
    class CollisionChecker
    {
        private static void reversesIfNeded(Point2D a1, Point2D a2)
        {
            if (a1.x > a2.x)
            {
                double tx = a1.x;
                double ty = a1.y;
                a1.x = a2.x;
                a1.y = a2.y;
                a2.x = tx;
                a2.y = ty;
                return;
            }
            if (a1.x == a2.x && a1.y > a2.y)
            {
                double tx = a1.x;
                double ty = a1.y;
                a1.x = a2.x;
                a1.y = a2.y;
                a2.x = tx;
                a2.y = ty;
            }
        }

        private static double getYfromLine(Point2D line, double x)
        {
            return line.x * x + line.y;
        }

        private static Point2D getLineParams(Point2D a, Point2D b)
        {
            double u = (b.y - a.y) / (b.x - a.x);
            double e = a.y - (u * a.x);
            return new Point2D(u, e);
        }

        private static bool isNumBetween(double n, double a, double b)
        {
            if ((n >= a && n <= b) || (n >= b && n <= a))
            {
                return true;
            }
            return false;
        }

        private static bool checkCollisionWithVertical(Point2D a1, Point2D a2, Point2D b1, Point2D b2)
        {
            if (b1.x == b2.x)
            {
                if (a1.x != b1.x)
                {
                    return false;
                }
                if (isNumBetween(a1.x, b1.x, b2.x) || isNumBetween(a2.x, b1.x, b2.x) || isNumBetween(b1.x, a1.x, a2.x) || isNumBetween(b2.x, a1.x, a2.x))
                {
                    return true;
                }
                return false;
            }
            if (!isNumBetween(a1.x, b1.x, b2.x))
            {
                return false;
            }
            if (isNumBetween(getYfromLine(getLineParams(b1, b2), a1.x), a1.y, a2.y))
            {
                return true;
            }
            return false;
        }

        public static bool checkCollicionSection(Point2D a1, Point2D a2, Point2D b1, Point2D b2)
        {
            Point2D l1 = getLineParams(a1, a2);
            Point2D l2 = getLineParams(b1, b2);

            if (Double.IsInfinity(l1.x) && Double.IsInfinity(l2.x) && a1.x == b1.x)
            {
                return true;
            }

            if (l1.x == l2.x)
            {
                return false;
            }

            if (a1.x == a2.x && checkCollisionWithVertical(a1, a2, b1, b2))
            {
                return true;
            }

            if (b1.x == b2.x && checkCollisionWithVertical(b1, b2, a1, a2))
            {
                return true;
            }

            double intX = (l2.y - l1.y) / (l1.x - l2.x);
            if (((intX >= a1.x && intX <= a2.x) || (intX >= a2.x && intX <= a1.x)) && ((intX >= b1.x && intX <= b2.x) || (intX >= b2.x && intX <= b1.x)))
            {
                return true;
            }

            return false;
        }

        public static ArrayList getRectWalls(ArrayList walls)
        {
            ArrayList newWallList = new ArrayList();
            foreach (Wall2D wall in walls)
            {
                Vector2D vect = new Vector2D(wall.firstPoint, wall.secondPoint);
                vect.Normalize();
                double topY = 0;
                double bottomY = 0;
                double leftX = 0;
                double rightX = 0;
                if (wall.firstPoint.x < wall.secondPoint.x)
                {
                    leftX = wall.firstPoint.x;
                    rightX = wall.secondPoint.x;
                }
                else
                {
                    leftX = wall.secondPoint.x;
                    rightX = wall.firstPoint.x;
                }
                if (wall.firstPoint.y < wall.secondPoint.y)
                {
                    topY = wall.firstPoint.y;
                    bottomY = wall.secondPoint.y;
                }
                else
                {
                    topY = wall.secondPoint.y;
                    bottomY = wall.firstPoint.y;
                }
                leftX -= Math.Abs(vect.X * 0.07);
                rightX += Math.Abs(vect.X * 0.07);
                topY -= Math.Abs(vect.Y * 0.07);
                bottomY += Math.Abs(vect.Y * 0.07);

                Wall2D newWallLong = new Wall2D(new Point2D(leftX, topY), new Point2D(rightX, bottomY));
                newWallList.Add(newWallLong);
            }
            return newWallList;
        }
    }
}

